import React, { Component } from 'react';
import {
  Modal,
  Icon,
  Table,
  Button,
  Popconfirm,
  message,
  Radio,
  DatePicker,
  Empty,
  Select
} from 'antd';
import { get } from 'lodash';
import PropTypes from 'prop-types';
import cn from 'classnames';
import { connect } from 'react-redux';
import './index.less';

const { RangePicker } = DatePicker;

class ExportModal extends Component {
  static propTypes = {
    visible: PropTypes.bool,
    onVisibleChange: PropTypes.func,
    listLoader: PropTypes.func,
    beforeDispatch: PropTypes.func,
    downloadDispatcher: PropTypes.func,
    downloader: PropTypes.func,
    deleter: PropTypes.func,
    enableRangePick: PropTypes.bool,
    target: PropTypes.string,
    multiConfigs: PropTypes.array,
    socketIO: PropTypes.object,
    socketIOInstance: PropTypes.object,
    isDetail: PropTypes.bool
  };
  static defaultProps = {
    target: ''
  };
  static defaultState = {
    filter: {
      range: 'thisWeek',
      start: '',
      end: ''
    },
    isDispatchDownloading: false,
    isLoading: false,
    rangePickerVisible: false,
    rangePickerOpen: false,
    currentMultiIndex: 0
  };
  constructor(props) {
    super(props);
    this.state = {
      list: [],
      ...ExportModal.defaultState
    };
  }

  componentDidMount() {
    this.bindSocketIO();
    if (this.props.visible) {
      this.loadExportsList();
    }
  }

  componentWillUnmount() {
    this.unbindSocketIO();
  }

  // eslint-disable-next-line
  UNSAFE_componentWillReceiveProps(props) {
    if (props.visible) {
      const { multiConfigs: newMultiConfigs } = props;
      const { multiConfigs: oldMultiConfigs } = this.props;
      if (
        JSON.stringify(newMultiConfigs) !== JSON.stringify(oldMultiConfigs) ||
        props.isDetail ||
        (!props.multiConfigs && !props.isDetail)
      ) {
        this.loadExportsList(props);
        this.setState(ExportModal.defaultState);
      }
    }
    if (props.socketIOInstance !== this.props.socketIOInstance) {
      this.bindSocketIO(props.socketIO);
    }
  }

  bindSocketIO = nextSocketIO => {
    let { socketIO } = this.props;
    if (nextSocketIO) {
      socketIO = nextSocketIO;
    }
    if (!socketIO) {
      return;
    }
    socketIO.on('notice_handler.download_file', this.refreshList);
  };

  unbindSocketIO = () => {
    const { socketIO } = this.props;
    if (!socketIO) {
      return;
    }
    socketIO.cancel('notice_handler.download_file', this.refreshList);
  };

  getConfigFromProps = (configKeys = [], props = this.props) => {
    const { multiConfigs } = props;
    const { currentMultiIndex } = this.state;
    let configs = configKeys.reduce(
      (total, configKey) => ({
        ...total,
        [configKey]: get(multiConfigs, `${currentMultiIndex}.${configKey}`) || props[configKey]
      }),
      {}
    );
    return configs;
  };

  refreshList = data => {
    let noticeTarget = get(data, 'target');
    let { target } = this.getConfigFromProps(['target']);
    if (noticeTarget && noticeTarget === target) {
      this.loadExportsList();
    }
  };

  loadExportsList = (props = this.props) => {
    this.setState({ isLoading: true });
    let { listLoader, target } = this.getConfigFromProps(['listLoader', 'target'], props);
    if (typeof listLoader !== 'function') {
      return message.error(`获取${target}列表失败`);
    }
    listLoader()
      .then(res => {
        const list = get(res, 'data.data.files', []);
        this.setState({
          list
        });
      })
      .finally(() => {
        this.loaded = true;
        this.setState({ isLoading: false });
      });
  };

  downloadExport = (filename, value) => {
    let { downloader, target } = this.getConfigFromProps(['downloader', 'target']);
    if (typeof downloader !== 'function') {
      return message.error(`下载${target}失败`);
    }
    message.info(`开始下载${filename}`);
    downloader(filename, value).catch(() => {
      message.error(`下载${target}失败`);
    });
  };

  deleteExport = (filename, value) => {
    let { deleter, target } = this.getConfigFromProps(['deleter', 'target']);
    if (typeof deleter !== 'function') {
      return message.error(`删除${target}失败`);
    }
    deleter(filename, value)
      .then(() => {
        message.success(`删除${target}成功`);
        this.loadExportsList();
      })
      .catch(() => {
        message.error(`删除${target}失败`);
      });
  };

  exportExport = () => {
    let {
      enableRangePick,
      beforeDispatch,
      target,
      downloader,
      downloadDispatcher
    } = this.getConfigFromProps([
      'enableRangePick',
      'beforeDispatch',
      'target',
      'downloader',
      'downloadDispatcher'
    ]);
    const { filter } = this.state;
    const body = enableRangePick ? filter : {};
    if (typeof beforeDispatch === 'function' && !beforeDispatch(body)) {
      return;
    }
    this.setState({ isDispatchDownloading: true });
    downloadDispatcher(body)
      .then(res => {
        let isDelay = get(res, 'data.data.delay', false);
        if (isDelay) {
          message.success('报告开始导出，请稍后打开弹框查看历史记录');
          this.setState({ isDispatchDownloading: false });
        } else {
          message.success(`成功导出${target}`);
          const list = get(res, 'data.data.files', []);
          const file = get(list, '0');
          const filename = get(file, 'filename');
          if (filename) {
            downloader(filename, get(list, '0'));
          }
          if (this) {
            const currentList = this.state.list;

            this.setState({
              list: [get(list, 0), ...currentList].filter(Boolean).slice(0, 7),
              isDispatchDownloading: false
            });
          }
        }
      })
      .catch(err => {
        if (get(err, 'message', '').indexOf('没有存活资产, 无法导出Excel报告') !== -1) {
          message.info(err.message);
          this.setState({ isDispatchDownloading: false });
          return;
        }
        message.error(get(err, 'message', '') || `导出${target}失败`);
        this.setState({ isDispatchDownloading: false });
      })
      .finally(() => {
        target = null;
        downloader = null;
      });
  };

  renderOperate = value => {
    const { filename } = value;
    return (
      <div>
        <Icon
          type="download"
          className="icon-download"
          onClick={() => this.downloadExport(filename, value)}
        />
        &nbsp;&nbsp;
        <Popconfirm
          title={'确认删除该记录吗?'}
          onConfirm={() => this.deleteExport(filename, value)}
        >
          <Icon type="delete" className="icon-delete" />
        </Popconfirm>
      </div>
    );
  };

  onSelectChange = e => {
    const timeScope = e.target.value;
    let { filter } = this.state;
    let rangePickerVisible = false;
    let rangePickerOpen = false;
    filter.range = timeScope;
    if (!timeScope) {
      rangePickerVisible = true;
      rangePickerOpen = true;
    } else {
      filter.start = '';
      filter.end = '';
    }
    this.setState({ filter, rangePickerVisible, rangePickerOpen });
  };

  onDateRangeChange = ([start, end] = []) => {
    let { filter } = this.state;
    filter.start = start ? start.format('YYYY-MM-DD 00:00:00') : '';
    filter.end = end ? end.format('YYYY-MM-DD 24:00:00') : '';
    this.setState({ filter });
  };

  disabledDate = date => {
    return date.valueOf() > Date.now();
  };

  onCancel = () => {
    let { filter } = this.state;
    let { onVisibleChange } = this.getConfigFromProps(['onVisibleChange']);
    onVisibleChange(false);
    filter.range = 'today';
    this.setState({ filter });
  };

  onMultiChange = value => {
    this.setState({ currentMultiIndex: value });
  };

  render() {
    let { visible, enableRangePick, target } = this.getConfigFromProps([
      'visible',
      'enableRangePick',
      'target',
      'downloader',
      'downloadDispatcher'
    ]);
    let { multiConfigs = [] } = this.props;
    let isMulti = Array.isArray(multiConfigs) && multiConfigs.length;
    const {
      list,
      isLoading,
      rangePickerVisible,
      filter,
      rangePickerOpen,
      isDispatchDownloading,
      currentMultiIndex = 0
    } = this.state;
    let { range } = filter;
    const columns = [
      {
        title: '名称',
        dataIndex: 'filename',
        width: 200
      },
      {
        title: '生成时间',
        dataIndex: 'created',
        width: 200
      },
      {
        title: '操作',
        render: this.renderOperate,
        width: 80
      }
    ];

    const footer = [
      <Button key="0" onClick={() => this.onCancel()}>
        关闭
      </Button>
    ];

    let operations = null;
    if (isMulti && enableRangePick) {
      operations = (
        <div>
          <div>请选择时间范围</div>
          <div className="range-picker-wrapper">
            <Radio.Group onChange={this.onSelectChange} value={range}>
              <Radio value="today">今日</Radio>
              <Radio value="thisWeek">本周</Radio>
              <Radio value="thisMonth">本月</Radio>
              <Radio value="all">全部</Radio>
              <Radio value="">自定义</Radio>
            </Radio.Group>
            <RangePicker
              open={rangePickerOpen}
              onOpenChange={rangePickerOpen => this.setState({ rangePickerOpen })}
              disabledDate={this.disabledDate}
              className="range-picker"
              onChange={this.onDateRangeChange}
              style={{ display: rangePickerVisible ? 'block' : 'none' }}
            />
          </div>
          <div className="operations">
            <Select
              value={currentMultiIndex}
              onSelect={this.onMultiChange}
              className="multi-select"
            >
              {multiConfigs.map(({ key = '' }, index) => (
                <Select.Option value={index} key={key}>
                  {key}
                </Select.Option>
              ))}
            </Select>
            <Button
              loading={isDispatchDownloading}
              className="export"
              type="primary"
              onClick={this.exportExport}
            >
              导出到服务器
            </Button>
          </div>
        </div>
      );
    } else if (isMulti && !enableRangePick) {
      operations = (
        <div className="operations">
          <Select value={currentMultiIndex} onChange={this.onMultiChange} className="multi-select">
            {multiConfigs.map(({ key = '' }, index) => (
              <Select.Option value={index} key={key}>
                {key}
              </Select.Option>
            ))}
          </Select>
          <Button
            loading={isDispatchDownloading}
            className="export"
            type="primary"
            onClick={this.exportExport}
          >
            导出到服务器
          </Button>
        </div>
      );
    } else if (!isMulti && enableRangePick) {
      operations = (
        <div>
          <div>请选择时间范围</div>
          <div className="operations">
            <Radio.Group onChange={this.onSelectChange} value={range}>
              <Radio value="today">今日</Radio>
              <Radio value="thisWeek">本周</Radio>
              <Radio value="thisMonth">本月</Radio>
              <Radio value="all">全部</Radio>
              <Radio value="">自定义</Radio>
            </Radio.Group>
            <Button
              loading={isDispatchDownloading}
              className="export"
              type="primary"
              onClick={this.exportExport}
            >
              导出
            </Button>
          </div>
          <RangePicker
            open={rangePickerOpen}
            onOpenChange={rangePickerOpen => this.setState({ rangePickerOpen })}
            disabledDate={this.disabledDate}
            className="range-picker"
            onChange={this.onDateRangeChange}
            style={{ display: rangePickerVisible ? 'block' : 'none' }}
          />
        </div>
      );
    } else if (!isMulti && !enableRangePick) {
      operations = (
        <div className="operations">
          <Button
            loading={isDispatchDownloading}
            className="export"
            type="primary"
            onClick={this.exportExport}
          >
            导出到服务器
          </Button>
        </div>
      );
    }

    return (
      <Modal
        maskClosable={false}
        className={cn('c-export-modal', 'no-header-bottom-lines', 'bottom-center', 'padding-24')}
        title={`导出${target}`}
        visible={visible}
        footer={footer}
        onCancel={() => this.onCancel()}
      >
        <div className="operations-wrapper">{operations}</div>
        <div className="result">
          <p className="result__title">历史导出{target}列表 (最近7次记录)</p>
          <Table
            dataSource={list.slice(0, 7)}
            columns={columns}
            pagination={false}
            rowKey="filename"
            loading={{ spinning: isLoading, tip: '加载中' }}
            locale={{
              emptyText: (
                <Empty
                  description={isLoading ? ' ' : '暂无数据'}
                  image={Empty.PRESENTED_IMAGE_SIMPLE}
                />
              )
            }}
            style={{ maxHeight: 200, overflow: 'auto', wordBreak: 'break-all' }}
          />
        </div>
      </Modal>
    );
  }
}

const mapStateToProps = state => {
  return {
    socketIO: get(state, 'socketIO.socketIO', null),
    socketIOInstance: get(state, 'socketIO.socketIO.socketIO', null)
  };
};

export default connect(
  mapStateToProps,
  null
)(ExportModal);
